package au.com.iglootech.TaxTimeToolTip.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.jdo.JdoCallback;
import org.springframework.stereotype.Component;

import au.com.iglootech.TaxTimeToolTip.UserSessionData;
import au.com.iglootech.TaxTimeToolTip.Entity.Company;
import au.com.iglootech.TaxTimeToolTip.Entity.Invoice;
import au.com.iglootech.TaxTimeToolTip.Entity.Task;
import au.com.iglootech.TaxTimeToolTip.dao.GenericDao;
import au.com.iglootech.TaxTimeToolTip.service.InvoiceTaxService;
import au.com.iglootech.TaxTimeToolTip.ui.invoice.InvoiceDateVO;
import au.com.iglootech.TaxTimeToolTip.util.DateUtils;
import au.com.iglootech.TaxTimeToolTip.util.InvoiceUtil;

import com.google.appengine.api.datastore.Key;

@Component(InvoiceTaxServiceImpl.BEANNAME)
public class InvoiceTaxServiceImpl implements InvoiceTaxService {

	public static final String BEANNAME = "InvoiceTaxServiceImpl";
	@Autowired
	private transient GenericDao genericDao;

	@Override
	@SuppressWarnings("unchecked")
	public List<Task> findInvoiceTaskByCompany(final Company company,
			final Date startDate, final Date endDate) {
		return new ArrayList<Task>(genericDao.getJdoTemplate().execute(
				new JdoCallback<Collection<Task>>() {
					public Collection<Task> doInJdo(PersistenceManager pm)
							throws JDOException {
						Query query = pm.newQuery(Task.class);
						query.setFilter("company == pCompany && invoiced == false && startDate >= pStartDate && startDate <= pEndDate");
						query.declareImports("import java.util.Date");
						query.declareParameters("Company pCompany, Date pStartDate, Date pEndDate");
						Date pStartDate = startDate == null ? DateUtils
								.systemStartDate() : startDate;
						Date pEndDate = endDate == null ? DateUtils
								.systemEndDate() : endDate;
						return pm.detachCopyAll((Collection<Task>) query
								.executeWithArray(company, pStartDate, pEndDate));
					}
				}));
	}

	@Override
	public Boolean invoiceTax(List<Task> tasks, Integer invoiceNumber,
			InvoiceDateVO invoiceDateVO) {
		List<Key> taskset = new ArrayList<Key>();
		for (Task task : tasks) {
			task.setInvoiced(true);
			task.setInvoicedDate(new Date());
			task.setInvoiceNumber(invoiceNumber);
			genericDao.save(task);
			taskset.add(task.getKey());
		}
		// create invoice number firstly
		Invoice invoice = new Invoice();
		invoice.setInvoiceNumber(invoiceNumber);
		invoice.setIsPaid(false);
		invoice.setTaskSets(taskset);
		invoice.setDetails(invoiceDateVO.getDetails());
		invoice = genericDao.save(invoice);
		return true;
	}

	@Override
	public List<Invoice> findUnPaidInvoice(String invoiceNumber, Date startDate, Date endDate) {
		if(invoiceNumber == null || invoiceNumber.equals(""))
		{
			return new ArrayList<Invoice>(genericDao.findByNamedQuery(
				Invoice.class, Invoice.FIND_UNPAID, null));
		}
		// get invoiceNumber
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("pInvoiceNumber", InvoiceUtil.parseInvoiceNumber(invoiceNumber));
		return new ArrayList<Invoice>(genericDao.findByNamedQuery(Invoice.class, Invoice.FIND_BY_INVOICE_NUMBER, params));
	}

	@Override
	public Boolean payInvoice(List<Invoice> invoices) {
		for (Invoice invoice : invoices) {
			invoice.setPaidDate(new Date());
			invoice.setIsPaid(true);
			invoice.setPaidBy(UserSessionData.getUserData().getUsername());
			genericDao.save(invoice);
		}
		return true;
	}

}
